﻿
Imports std

Namespace internalFunctions
    Public Class threadDelegate
        Private _ctx As context = Nothing
        Private _functionName As String = Nothing
        Private _rtn As bare_variable = Nothing
        Private _rst As Boolean = False
        Private _finish As Boolean = False

        Public Sub New(ByVal ctx As context, ByVal functionName As String)
            Me._ctx = ctx
            copy(Me._functionName, functionName)
        End Sub

        Public Shared Sub threadWorkDelegate(ByVal obj As Object)
            Dim para As threadDelegate = Nothing
            para = convertor.cast(Of threadDelegate)(obj)
            para._finish = False
            para._rst = para.context().invoke(para.functionName(), para._rtn)
            para._finish = True
        End Sub

        Public Function result() As bare_variable
            Return _rtn
        End Function

        Public Function finish() As Boolean
            Return _finish
        End Function

        Public Function context() As context
            Return _ctx
        End Function

        Public Function functionName() As String
            Return _functionName
        End Function
    End Class

    'parameters, threadcount, int, optional
    'return, var, an instance of threadpool
    Public Class createThreadPool
        Inherits internalFunction

        Public Class parameters
            Public Const threadcount As String = "threadcount"
        End Class

        Private Shared m As iParametersMapping = Nothing
        Private Shared pools As vector(Of threadpool) = Nothing

        Shared Sub New()
            initialMapping(m, parameters.threadcount)
            pools = New vector(Of threadpool)()
            AddHandler applicationShutdown, AddressOf _finalize
        End Sub

        Private Shared Sub _finalize()
            assert(Not pools Is Nothing)
            For i As Int64 = 0 To pools.size() - 1
                pools(i).stop()
            Next
        End Sub

        Public Sub New()
            MyBase.New("threadpool.create", m)
        End Sub

        Protected Overrides Function invoke(ByVal ctx As context, ByRef output As bare_variable) As Boolean
            Dim rtn As threadpool = Nothing
            Dim threadcount As Int64
            If Not ctx.findVariableInt(parameters.threadcount, threadcount) Then
                rtn = New threadpool(AddressOf threadDelegate.threadWorkDelegate)
            Else
                rtn = New threadpool(AddressOf threadDelegate.threadWorkDelegate, threadcount)
            End If
            assert(pools.push_back(rtn))
            output = New bare_variable(typeDefination.var, rtn)

            Return True
        End Function
    End Class

    'parameters, tp, var, an instance of threadpool, created by threadpool.create
    '            functionName, any, convert to string, the start function name of this thread
    '            other parameters will be sent to the new thread & function
    'return, var, an instance of threadDelegate, to get the thread status / return value / invoke result
    Public Class threadpoolInsertJob
        Inherits internalFunction

        Public Class parameters
            Public Const tp As String = "tp"
            Public Const functionName As String = "functionName"
        End Class

        Private Shared m As iParametersMapping = Nothing

        Shared Sub New()
            initialMapping(m, parameters.tp, parameters.functionName)
        End Sub

        Public Sub New()
            MyBase.New("threadpool.insertjob", m)
        End Sub

        Private Shared Function iterateVariablesInvoke(ByVal name As String, ByVal var As bare_variable, _
                                                       ByRef obj As Object) As Boolean
            Dim ctx As context = Nothing
            ctx = convertor.cast(Of context)(obj)
            If Not strsame(name, parameters.tp) AndAlso Not strsame(name, parameters.functionName) Then
                Return ctx.insertVariable(name, var) <> ctx.variables_end()
            Else
                Return True
            End If
        End Function

        Protected Overrides Function invoke(ByVal ctx As context, ByRef output As bare_variable) As Boolean
            Dim tp As threadpool = Nothing
            If ctx.findVariable(parameters.tp, tp) Then
                Dim functionName As String = Nothing
                If ctx.findVariableStr(parameters.functionName, functionName) Then
                    Dim newctx As context = Nothing
                    copy(newctx, context.currentContext())
                    If Not ctx.iterateVariables(AddressOf iterateVariablesInvoke, obj:=newctx) Then
                        raiseError("cannot iterateVariables.", errorHandle.errorType.exclamation)
                        Return False
                    End If

                    Dim para As threadDelegate = Nothing
                    para = New threadDelegate(newctx, functionName)
                    tp.insertJob(para)
                    output = New bare_variable(typeDefination.var, para)
                    Return True
                Else
                    raiseError("expect parameters " + parameters.functionName, errorHandle.errorType.user)
                    Return False
                End If
            Else
                raiseError("expect parameters " + parameters.tp, errorHandle.errorType.user)
                Return False
            End If
        End Function
    End Class
End Namespace